import { chManager } from './defaultconfig.js';
import { DSP } from './dsphandler.js';
import { EQUtil } from './eq_util.js';

const styles = {
    mask: {
        margin: "0",
        padding: "0",
        width: "100%",
        height: "100%",
        border: "none",
        background: "transparent",
        boxSizing: "border-box",
        position: "absolute",
        top: "0px",
        left: "0px",
        zIndex: "2"
    },
    item: {
        margin: "0",
        padding: "0",
        width: "0px",
        height: "60px",
        border: "none",
        // background: "rgba(255, 255, 255, 0.1)",
        background: "transparent",
        boxSizing: "border-box",
        position: "absolute",
        top: "0px",
        left: "0px",
        display: "grid",
        gridTemplateRows: 'repeat(3,1fr)',
        alignItems: "center",
    },
    num: {
        color: "white",
        textAlign: "center",
        background: "transparent",
        position: "relative",
        fontSize: '12px',
        width: '20px',
        cursor: "grabbing" // 拖动中光标 
    },
    cell: {
        width: '100%',
        height: '100%',
        background: 'transparent',
        justifyContent: 'center',
        alignItems: "center",
        fontSize: '10px',
        textAlign: 'center',
        position: 'relative',
    },
    point: {
        width: '10px',
        aspectRatio: 1,
        background: 'transparent',
        border: '1px solid #ccc',
        borderRadius: '50%',
        cursor: 'pointer',
        transition: 'background-color 0.3s',
        visibility: 'hidden', // 隐藏但保留空间
        position: 'absolute'
    }
};

export class EqChartMask {

    constructor(myChartID, points, { delay = 30, onChange = null } = {}) {
        this.myChartID = myChartID;
        this.onChange = onChange || null;
        this.delay = delay;
        this.isSend = false;
        this.points = points;
        this.itemRefs = new Map();
        this.createDOM();
    }

    createDOM() {
        this.my_chart = document.getElementById(this.myChartID);
        //遮罩
        this.mask = document.createElement('div');
        this.mask.id = "my_chart_mask";
        Object.assign(this.mask.style, styles.mask);
        this.my_chart.appendChild(this.mask);
    }

    ///全部更新
    refreshUI() {
        const item_width = this.my_chart.clientWidth / this.points.length * 2 - 30;
        if (this.itemRefs.size > 0) {
            this.itemRefs.forEach(ref => ref.item.width = item_width + "px");
        } else {
            const fragment = document.createDocumentFragment();

            this.points.forEach((x, index) => {
                const item = this.initItem(x, item_width);
                const num = this.initNum(index);
                const top = this.initCellDiv(index, 1, item);
                const mid = this.initCellDiv(index, 2, item);
                const bottom = this.initCellDiv(index, 3, item);
                const leftPoint = this.initPoint(index, item_width, { isRight: false });
                const rightPoint = this.initPoint(index, item_width, { isRight: true });

                mid.appendChild(leftPoint);
                mid.appendChild(num);
                mid.appendChild(rightPoint);
                item.appendChild(top);
                item.appendChild(mid);
                item.appendChild(bottom);

                fragment.appendChild(item);
                this.itemRefs.set(index, { item, num, top, bottom, leftPoint, rightPoint });

                this.setupDragEvents(item, index);
                this.setupPointEvents(leftPoint);
                this.setupPointEvents(rightPoint);
            });
            this.mask.appendChild(fragment);
        }
    }
    ///初始化整个频点滑动区域背景
    initItem(x, width) {
        const item = document.createElement("div");
        Object.assign(item.style, styles.item);
        item.style.width = width + "px";
        item.style.top = this.my_chart.clientHeight / 2 - 20 + "px";
        item.style.left = x - this.mask.getBoundingClientRect().left / 2 + "px";
        return item;
    }

    ///初始化频点的数字
    initNum(index) {
        const label = document.createElement("div");
        Object.assign(label.style, styles.num);
        label.textContent = `${index + 1}`;
        return label;
    }

    ///初始化背景区域上中下三个cell的背景
    initCellDiv(index, i, item) {
        const div = document.createElement('div');
        Object.assign(div.style, styles.cell);
        div.style.visibility = i === 2 ? 'visible' : 'hidden'; // 隐藏但保留空间
        div.style.display = i === 2 ? 'flex' : 'block';       // 非 flex 时用 block
        div.style.height = `${parseInt(item.style.height) / 3}px`;
        div.index = index;
        div.id = `ball_cell_${index}` + ['top', 'mid', 'bottom'][i - 1];
        return div;
    }

    ///初始化捏合变化Q值的小圆点
    initPoint(index, width, { isRight = true }) {
        const pointcheck = document.createElement('div');
        Object.assign(pointcheck.style, styles.point);
        pointcheck.isLeft = !isRight;
        pointcheck.index = index;
        pointcheck.className = "point_check_div";
        pointcheck.style.left = isRight ? `${width / 4 * 3 + 5}px` : `${width / 4 - 5}px`;
        return pointcheck;
    }

    ///添加 频点的手势响应
    setupDragEvents(element, index) {
        const ref = this.itemRefs.get(index);
        const num = ref.num;
        let isDragging = false;
        let offsetX, offsetY;

        const handleMouseMove = (e) => {
            if (!isDragging) return;
            // this.updatePosition(ball, e.clientX - offsetX, e.clientY - offsetY);
            this.handleDragMove(index, e.clientX - offsetX, e.clientY - offsetY);
        };

        const handleMouseUp = () => {
            if (isDragging) {
                isDragging = false;
                element.style.zIndex = "1";
                document.removeEventListener("mousemove", handleMouseMove);
                document.removeEventListener("mouseup", handleMouseUp);
            }
        };

        num.onmousedown = (e) => {
            isDragging = true;
            this.itemRefs.forEach(ref => ref.item.style.zIndex = "1");
            element.style.zIndex = '100';

            // 计算鼠标在ball的偏移量
            const rect = element.getBoundingClientRect();
            offsetX = e.clientX - rect.left;
            offsetY = e.clientY - rect.top;
            this.updateItemtatus(index);

            // 绑定到 document
            document.addEventListener("mousemove", handleMouseMove);
            document.addEventListener("mouseup", handleMouseUp);

            e.preventDefault();
        };
    }

    ///添加左  ｜ 右，小圆点手势 响应
    setupPointEvents(point) {
        let isDragging = false;
        let startX = 0;
        let otherPoint;

        const handleMouseMove = (e) => {
            e.stopPropagation();
            e.preventDefault();
            if (!isDragging) return;

            const ref = this.itemRefs.get(point.index);
            const item = ref.item; // 获取 ball 元素
            const num = ref.num;

            // 检查鼠标是否在 ball 范围内
            const itemRect = item.getBoundingClientRect()
            if (
                e.clientX < itemRect.left ||
                e.clientX > itemRect.right ||
                e.clientY < itemRect.top ||
                e.clientY > itemRect.bottom
            ) {
                // 如果超出范围，立即停止拖拽
                handleMouseUp();
                return;
            }

            // 获取父元素位置（关键修正点）
            const parentRect = point.parentElement.getBoundingClientRect();
            const mouseX = e.clientX - parentRect.left; // 转换为相对坐标
            const deltaX = mouseX - startX;
            startX = mouseX;

            this.updatePointPosition(point, otherPoint, item, num, deltaX, point.index);
        };

        const handleMouseUp = (e) => {
            isDragging = false;
            point.style.transition = 'background-color 0.3s';
            point.style.background = 'transparent';
            otherPoint.style.background = 'transparent';
            point.style.zIndex = "";
            otherPoint.style.zIndex = "";
            document.removeEventListener("mousemove", handleMouseMove);
            document.removeEventListener("mouseup", handleMouseUp);
        }

        point.onmousedown = (e) => {
            e.stopPropagation();
            e.preventDefault();
            window.getSelection().removeAllRanges(); // 清除已有文本选中

            const ref = this.itemRefs.get(point.index);
            otherPoint = point.isLeft ? ref.rightPoint : ref.leftPoint;

            const parentRect = point.parentElement.getBoundingClientRect();
            startX = e.clientX - parentRect.left; // 起始位置转为相对坐标
            isDragging = true;

            point.style.transition = 'none'; // 拖动时禁用过渡
            point.style.background = '#ccc';
            otherPoint.style.background = '#ccc';
            point.style.zIndex = "100";
            otherPoint.style.zIndex = "100";

            // 绑定到 document
            document.addEventListener("mousemove", handleMouseMove);
            document.addEventListener("mouseup", handleMouseUp);
        }
    }

    updatePointPosition(point, otherPoint, item, num, deltaX, index) {
        const item_w = item.clientWidth;
        const currentLeft = parseInt(point.style.left);
        let newLeft = currentLeft + deltaX;

        // 动态计算边界
        const pointWidth = point.clientWidth;
        const labelWidth = num.clientWidth;
        const minLeft = point.isLeft ? 0 : item_w / 2 + labelWidth / 2;
        const maxLeft = point.isLeft ? item_w / 2 - pointWidth - labelWidth / 2 : item_w - pointWidth;

        newLeft = Math.max(minLeft, Math.min(maxLeft, newLeft));
        const otherNewLeft = item_w - newLeft - pointWidth;

        // 更新当前点,   // 对称更新另一
        point.style.left = `${newLeft}px`;
        otherPoint.style.left = `${otherNewLeft}px`;

        this.updateQValue(index, newLeft, otherNewLeft, item_w, pointWidth, labelWidth, point.isLeft);
    }

    updateQValue(index, newLeft, otherNewLeft, item_w, pointWidth, labelWidth, isLeft) {
        const sign = chManager.current_chlist[0].sign_list[index];
        const scale_q = sign.max_q / (item_w / 2 - pointWidth - labelWidth / 2);
        let q = parseFloat(isLeft ? newLeft : otherNewLeft) * scale_q;
        q = Math.max(sign.min_q, Math.min(q, sign.max_q));
        q = Math.round(q * 10) / 10;

        this.updateSign(sign.gain, sign.freq, q, index);
    }

    /**
    * 更新ball的位置，x
    * @param {number} index - ball
    * @param {number} ball_left - ball的左顶点
    * @param {number} ball_top - ball的上顶点
    */
    updatePosition(index, ball_left, ball_top) {

        const ref = this.itemRefs.get(index);
        const item = ref.item;
        const num = ref.num;
        const w = item.clientWidth;

        item.style.width = w + "px";
        // 获取父容器边界信息（只计算一次）
        const parentRect = this.mask.getBoundingClientRect();
        const parentWidth = this.mask.clientWidth;
        const parentHeight = this.mask.clientHeight;

        // // 计算中心点偏移（假设需要以中心点为基准）
        const centerOffsetX = item.clientWidth / 2;
        const centerOffsetY = item.clientHeight / 2;

        // 计算相对位置（减去父容器偏移和初始点击偏移）
        const newX = ball_left - parentRect.left - centerOffsetX;
        const newY = ball_top - parentRect.top - centerOffsetY;

        // 边界检查（动态计算最大范围）
        const maxX = parentWidth - centerOffsetX;
        const maxY = parentHeight - centerOffsetY;

        // 应用边界限制
        const clampedX = Math.max(-centerOffsetX, Math.min(newX, maxX));
        const clampedY = Math.max(-centerOffsetY, Math.min(newY, maxY));

        // 更新位置
        item.style.left = `${clampedX}px`;
        item.style.top = `${clampedY}px`;
        item.style.zIndex = "100"

        ///更新左右圆点的位置
        const leftPoint = ref.leftPoint;
        const rightPoint = ref.rightPoint;
        const pointWidth = leftPoint.clientWidth;
        const numWidth = num.clientWidth;

        const sign = chManager.current_chlist[0].sign_list[index];
        const scale_q = (w / 2 - pointWidth - numWidth / 2) / sign.max_q;
        leftPoint.style.left = `${scale_q * sign.q}px`;
        rightPoint.style.left = `${w - pointWidth - scale_q * sign.q}px`;

        this.updateSign(sign.gain, sign.freq, sign.q, index, { onlyRefreshUI: true });
    }

    handleDragMove(index, ball_left, ball_top) {
        const ref = this.itemRefs.get(index);
        const item = ref.item;
        const w = item.clientWidth / 2;
        const h = item.clientHeight / 2;

        ///算出ball的中心点到左顶点的距离
        let centerX = ball_left + w;
        let centerY = ball_top + h;

        ///计算ball的中心点距离父元素的左顶点的距离
        const parentRect = this.mask.getBoundingClientRect();
        const parentWidth = this.mask.clientWidth;
        const parentHeight = this.mask.clientHeight;

        centerX = centerX - parentRect.left;
        centerY = centerY - parentRect.top;

        ///根据移动的gain上下位置，决定ball_content是显示上面的还是下面的
        const over_top = centerY - parentRect.top <= 0;
        const over_bottom = parentRect.top + parentHeight - centerY <= 0;
        this.itemRefs.forEach((ref, i) => {
            ref.top.style.visibility = over_top || i !== index ? 'hidden' : 'visible';
            ref.bottom.style.visibility = over_bottom || i !== index || !over_top ? 'hidden' : 'visible';
        });

        //1.  把中心点x，转换成Freq
        const freq = Math.round(EQUtil.deInt(centerX, this.my_chart.clientWidth, 0));

        //2. 把中心点y，转换成Gain
        const sign = chManager.current_chlist[0].sign_list[index];
        const scale = (sign.max_gain - sign.min_gain) / this.mask.clientHeight;
        let gain = centerY * scale;
        gain = Math.max(0, Math.min(gain, (sign.max_gain - sign.min_gain)));
        gain = Math.round((parseInt(sign.max_gain) - gain) * 10) / 10;

        this.updateSign(gain, freq, sign.q, index);
    }

    ///
    updateItemtatus(index) {
        this.itemRefs.forEach((ref, i) => {
            ref.top.style.visibility = i === index ? 'visible' : 'hidden';
            ref.bottom.style.visibility = 'hidden';
            ref.leftPoint.style.visibility = i === index ? 'visible' : 'hidden';
            ref.rightPoint.style.visibility = i === index ? 'visible' : 'hidden';
        });
    }


    updateSign(gain, freq, q, index, { onlyRefreshUI = false } = {}) {
        const ref = this.itemRefs.get(index);
        if (!ref) return;
        const infoText = `G:${gain} F:${freq} Q:${q}`;
        ref.top.textContent = infoText;
        ref.bottom.textContent = infoText;

        if (onlyRefreshUI) return;

        chManager.current_chlist.forEach(ch => {
            ch.sign_list[index].freq = Math.round(freq);
            ch.sign_list[index].gain = gain;
            ch.sign_list[index].q = q;
        });

        if (this.onChange) {
            this.onChange();
        }
        ///
        if (this.isSend === false) {
            DSP.updateEQ(gain, freq, q, index);
            this.isSend = true;
            setTimeout(() => this.isSend = false, this.delay);
        }
    }
}